home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / UUPC11QS.ARJ / UUX.C < prev    next >
C/C++ Source or Header  |  1991-11-22  |  37KB  |  1,037 lines

  1. /*
  2.       Program:    uux.c              27 August 1991
  3.       Author:     Mitch Mitchell
  4.       Email:      mitch@harlie.lonestar.org
  5.  
  6.       Much of this code is shamelessly taken from extant code in
  7.       UUPC/Extended.
  8.  
  9.       Usage:      uux [ options ] command-string
  10.  
  11.                Where [ options ] are:
  12.  
  13.      -aname    Use name as the user identification replacing the initiator
  14.                user-id.  (Notification will be returned to the user.)
  15.  
  16.      -b        Return whatever standard input was provided to the uux command
  17.                if the exit status is non-zero.
  18.  
  19.      -c        Do not copy local file to the spool directory for transfer to
  20.                the remote machine (default).
  21.  
  22.      -C        Force the copy of local files to the spool directory for
  23.                transfer.
  24.  
  25.      -e        Remote system should use sh to execute commands.
  26.  
  27.      -E        Remote system should use exec to execute commands.
  28.  
  29.      -ggrade   Grade is a single letter/number; lower ASCII sequence
  30.                characters will cause the job to be transmitted earlier during
  31.                a particular conversation.
  32.  
  33.      -j        Output the jobid ASCII string on the standard output which is
  34.                the job identification.  This job identification can be used by
  35.                uustat to obtain the status or terminate a job.
  36.  
  37.      -n        Do not notify the user if the command fails.
  38.  
  39.      -p        The standard input to uux is made the standard input to the
  40.                command-string.
  41.  
  42.      -r        Do not start the file transfer, just queue the job.
  43.                (Currently uux does not attempt to start the transfer
  44.                 regardless of the presense of this option).
  45.  
  46.      -sfile    Report status of the transfer in file.
  47.  
  48.      -xdebug_level
  49.                Produce debugging output on the standard output.  The
  50.                debug_level is a number between 0 and ??; higher numbers give
  51.                more detailed information.
  52.  
  53.      -z        Send success notification to the user.
  54.  
  55.  
  56.       The command-string is made up of one or more arguments that
  57.       look like a normal command line, except that the command and
  58.       filenames may be prefixed by system-name!.  A null
  59.       system-name is interpreted as the local system.
  60.  
  61. */
  62.  
  63. /*--------------------------------------------------------------------*/
  64. /*         System include files                                       */
  65. /*--------------------------------------------------------------------*/
  66.  
  67. #include <stdio.h>
  68. #include <io.h>
  69. #include <string.h>
  70. #include <time.h>
  71. #include <stdlib.h>
  72. #include <fcntl.h>
  73. #include <sys/types.h>
  74. #include <sys/stat.h>
  75.  
  76. /*--------------------------------------------------------------------*/
  77. /*         Local include files                                        */
  78. /*--------------------------------------------------------------------*/
  79.  
  80. #include  "lib.h"
  81. #include  "hlib.h"
  82. #include  "getopt.h"
  83. #include  "getseq.h"
  84. #include  "expath.h"
  85. #include  "import.h"
  86. #include  "pushpop.h"
  87. #include  "security.h"
  88. #include  "hostable.h"
  89. #include  "timestmp.h"
  90.  
  91. /*--------------------------------------------------------------------*/
  92. /*        Define current file name for panic() and printerr()         */
  93. /*--------------------------------------------------------------------*/
  94.  
  95. currentfile();
  96.  
  97. /*--------------------------------------------------------------------*/
  98. /*                          Global variables                          */
  99. /*--------------------------------------------------------------------*/
  100.  
  101. typedef enum {
  102.           FLG_USE_USERID,
  103.           FLG_OUTPUT_JOBID,
  104.           FLG_READ_STDIN,
  105.           FLG_QUEUE_ONLY,
  106.           FLG_NOTIFY_SUCCESS,
  107.           FLG_NONOTIFY_FAIL,
  108.           FLG_COPY_SPOOL,
  109.           FLG_RETURN_STDIN,
  110.           FLG_STATUS_FILE,
  111.           FLG_USE_EXEC,
  112.           FLG_MAXIMUM
  113.        } UuxFlags;
  114.  
  115. typedef enum {
  116.       DATA_FILE   = 0,
  117.       INPUT_FILE  = 1,
  118.       OUTPUT_FILE = 2
  119.       } FileType;
  120.  
  121. static boolean flags[FLG_MAXIMUM] = {
  122.                                         FALSE,
  123.                                         FALSE,
  124.                                         FALSE,
  125.                                         FALSE,
  126.                                         FALSE,
  127.                                         FALSE,
  128.                                         FALSE,
  129.                                         FALSE,
  130.                                         FALSE,
  131.                                         FALSE
  132.                                     };
  133. static FILE* datain = NULL;
  134. static char* st_out = NULL;
  135. static char* user_id = NULL;
  136. static char  grade = 'Z';          /* Default grade of service */
  137.  
  138. static char  job_id[15];
  139.  
  140. static char* spool_fmt = SPOOLFMT;
  141. static char* dataf_fmt = DATAFFMT;
  142.  
  143. static char* send_cmd  = "S %s %s %s - %s 0666\n";
  144.  
  145. /*--------------------------------------------------------------------*/
  146. /*                        Internal prototypes                         */
  147. /*--------------------------------------------------------------------*/
  148.  
  149. void main(int  argc, char  **argv);
  150. static void usage( void );
  151. static char *SwapSlash(char *p);
  152. static boolean cp(char *from, char *to);
  153. static boolean split_path(char *path, char *system, char *file, boolean expand);
  154. static boolean CopyData( const char *input, const char *output);
  155. static boolean remove_parens(char *string);
  156. static boolean do_uuxqt(char *job_name, char *src_syst, char *src_file, char *dest_syst, char *dest_file);
  157. static boolean do_copy(char *src_syst, char *src_file, char *dest_syst, char *dest_file);
  158. static boolean do_remote(int optind, int argc, char **argv);
  159. static void preamble(FILE* stream);
  160. static char subseq( void );
  161.  
  162. /*--------------------------------------------------------------------*/
  163. /*    u s a g e                                                       */
  164. /*                                                                    */
  165. /*    Report flags used by program                                    */
  166. /*--------------------------------------------------------------------*/
  167.  
  168. static void usage()
  169. {
  170.       fprintf(stderr, "Usage: uux\t[-c|-C] [-e|-E] [-b] [-gGRADE] [-p] [-j] [-n] [-r] [-sFILE]\\\n\
  171. \t\t[-aNAME] [-z] [-] [-xDEBUG_LEVEL] command-string\n");
  172. }
  173.  
  174.  
  175. /*--------------------------------------------------------------------*/
  176. /*    s w a p s l a s h                                               */
  177. /*                                                                    */
  178. /*    Change backslash in a directory path to forward slash           */
  179. /*--------------------------------------------------------------------*/
  180.  
  181. static char *SwapSlash(char *p)
  182. {
  183.      char *q = p;
  184.  
  185.      while (*q) {
  186.         if (*q ==  '\\')
  187.            *q = '/';
  188.         q++;
  189.      }
  190.      return p;
  191. };
  192.  
  193. /*--------------------------------------------------------------------*/
  194. /*    c p                                                             */
  195. /*                                                                    */
  196. /*    Copy Local Files                                                */
  197. /*--------------------------------------------------------------------*/
  198.  
  199. static boolean cp(char *from, char *to)
  200. {
  201.       int  fd_from, fd_to;
  202.       int  nr;
  203.       int  nw = -1;
  204.       char buf[BUFSIZ];            /* faster if we alloc a big buffer */
  205.  
  206.       /* This would be even faster if we determined that both files
  207.          were on the same device, dos >= 3.0, and used the dos move
  208.          function */
  209.  
  210.       if ((fd_from = open(from, O_RDONLY | O_BINARY)) == -1)
  211.          return FALSE;        /* failed */
  212.  
  213.       /* what if the to is a directory? */
  214.       /* possible with local source & dest uucp */
  215.  
  216.       if ((fd_to = open(to, O_CREAT | O_BINARY | O_WRONLY, S_IWRITE | S_IREAD)) == -1) {
  217.          close(fd_from);
  218.          return FALSE;        /* failed */
  219.          /* NOTE - this assumes all the required directories exist!  */
  220.       }
  221.  
  222.       while  ((nr = read(fd_from, buf, sizeof buf)) > 0 &&
  223.          (nw = write(fd_to, buf, nr)) == nr)
  224.          ;
  225.  
  226.       close(fd_to);
  227.       close(fd_from);
  228.  
  229.       if (nr != 0 || nw == -1)
  230.          return FALSE;        /* failed in copy */
  231.       return TRUE;
  232. }
  233.  
  234.  
  235. /*--------------------------------------------------------------------*/
  236. /*    C o p y D a t a                                                 */
  237. /*                                                                    */
  238. /*    Copy data into its final resting spot                           */
  239. /*--------------------------------------------------------------------*/
  240.  
  241. static boolean CopyData( const char *input, const char *output)
  242. {
  243.    FILE    *datain;
  244.    FILE    *dataout;
  245.    char     buf[BUFSIZ];
  246.    boolean  status = TRUE;
  247.  
  248.    if ( (dataout = FOPEN(output, "w", BINARY)) == NULL ) {
  249.       printerr(output);
  250.       printmsg(0,"uux: Cannot open spool file \"%s\" for output",
  251.                output);
  252.       return FALSE;
  253.    }
  254.  
  255. /*--------------------------------------------------------------------*/
  256. /*                      Verify the input opened                       */
  257. /*--------------------------------------------------------------------*/
  258.  
  259.    if (input == NULL)
  260.    {
  261.       datain = stdin;
  262.       setmode(fileno(stdin), O_BINARY);   /* Don't die on control-Z, etc */
  263.    }
  264.    else
  265.       datain = FOPEN(input, "r", BINARY);
  266.  
  267.    if (datain == NULL) {
  268.       printerr(input);
  269.       printmsg(0,"Unable to open input file \"%s\"",
  270.                (input == NULL ? "stdin" : input));
  271.       fclose(dataout);
  272.       return FALSE;
  273.    } /* datain */
  274.  
  275. /*--------------------------------------------------------------------*/
  276. /*                       Loop to copy the data                        */
  277. /*--------------------------------------------------------------------*/
  278.  
  279.    while (fgets(buf, BUFSIZ, datain) != 0)
  280.    {
  281.       if (fputs(buf, dataout) == EOF)     /* I/O error?               */
  282.       {
  283.          printerr("dataout");
  284.          printmsg(0,"I/O error on \"%s\"", output);
  285.          fclose(dataout);
  286.          return FALSE;
  287.       } /* if */
  288.    } /* while */
  289.  
  290. /*--------------------------------------------------------------------*/
  291. /*                      Close up shop and return                      */
  292. /*--------------------------------------------------------------------*/
  293.  
  294.    if (ferror(datain))        /* Clean end of file on input?          */
  295.    {
  296.       printerr(input);
  297.       clearerr(datain);
  298.       status = FALSE;
  299.    }
  300.  
  301.    if (input != NULL)
  302.        fclose(datain);
  303.  
  304.    fclose(dataout);
  305.    return status;
  306.  
  307. } /* CopyData */
  308.  
  309. /*--------------------------------------------------------------------*/
  310. /*    r e m o v e _ p a r e n s                                       */
  311. /*                                                                    */
  312. /*--------------------------------------------------------------------*/
  313.  
  314. static boolean remove_parens(char *string)
  315. {
  316.       int len = strlen(string);
  317.  
  318.       if ((string[0] != '(') || (string[len - 1] != ')'))
  319.           return FALSE;
  320.  
  321.       strcpy(string, &string[1]);
  322.       string[len - 2] = '\0';
  323.       return TRUE;                 /* and we're done */
  324. }
  325.  
  326. /*--------------------------------------------------------------------*/
  327. /*    s p l i t _ p a t h                                             */
  328. /*--------------------------------------------------------------------*/
  329.  
  330. static boolean split_path(char *path,
  331.                           char *sysname,
  332.                           char *file,
  333.                           boolean expand)
  334. {
  335.       char *p_left;
  336.       char *p_right;
  337.       char *p = path;
  338.  
  339.       *sysname = *file = '\0';    /* init to nothing */
  340.  
  341. /*--------------------------------------------------------------------*/
  342. /*                if path is wildcarded then error                    */
  343. /*--------------------------------------------------------------------*/
  344.  
  345.       if (strcspn(path, "*?[") < strlen(path))
  346.          return FALSE;
  347.  
  348.       p_left = strchr(p, '!');         /* look for the first bang */
  349.       if (p_left == NULL || (p_left == p))
  350.       {                                /* not a remote path */
  351.          if (p_left == p )
  352.          {
  353.             strcpy(file, p+1);         /* so just return filename */
  354.             if ( expand && (expand_path(file, NULL, homedir, NULL) == NULL) )
  355.                return FALSE;
  356.          }
  357.          else
  358.             strcpy(file, p);           /* so just return filename */
  359.          strcpy(sysname, nodename);
  360.          return TRUE;
  361.       }
  362.  
  363.       p_right = strrchr(p, '!');      /* look for the last bang */
  364.       strcpy(file, p_right + 1);      /* and thats our filename */
  365.  
  366.       strncpy(sysname, p, p_left - p); /* and we have a system thats not us */
  367.       sysname[p_left - p] = '\0';
  368.  
  369.       /* now see if there is an intermediate path */
  370.  
  371.       if (p_left != p_right)  {        /* yup - there is */
  372.           return FALSE;
  373.       }
  374.  
  375. #if 0
  376.       if (expand && (strcspn(file, "~") >= strlen(file)) )
  377.           if (expand_path(file, NULL, homedir, NULL) == NULL)
  378.              return FALSE;
  379. #endif
  380.  
  381.       return TRUE;                     /* and we're done */
  382. }
  383.  
  384. /*--------------------------------------------------------------------*/
  385. /*    d o _ u u x q t                                                 */
  386. /*                                                                    */
  387. /*    Generate a UUXQT command file for local system                  */
  388. /*--------------------------------------------------------------------*/
  389.  
  390. static boolean do_uuxqt(char *job_name,
  391.                         char *src_syst,
  392.                         char *src_file,
  393.                         char *dest_syst,
  394.                         char *dest_file)
  395. {
  396.    long seqno = 0;
  397.    char *seq  = NULL;
  398.    FILE *stream;              /* For writing out data                 */
  399.  
  400.    char msfile[FILENAME_MAX]; /* MS-DOS format name of files          */
  401.    char msname[22];           /* MS-DOS format w/o path name          */
  402.    char ixfile[15];           /* eXecute file for local system,
  403.                                  UNIX format name for local system    */
  404.  
  405. /*--------------------------------------------------------------------*/
  406. /*          Create the UNIX format of the file names we need          */
  407. /*--------------------------------------------------------------------*/
  408.  
  409.    seqno = getseq();
  410.    seq = JobNumber( seqno );
  411.  
  412.    sprintf(ixfile, spool_fmt, 'X', nodename, grade , seq);
  413.  
  414. /*--------------------------------------------------------------------*/
  415. /*                     create local X (xqt) file                      */
  416. /*--------------------------------------------------------------------*/
  417.  
  418.    importpath( msname, ixfile, nodename);
  419.    mkfilename( msfile, spooldir, msname);
  420.  
  421.    if ( (stream = FOPEN(msfile, "w", BINARY)) == NULL ) {
  422.       printerr(msfile);
  423.       printmsg(0, "uux: cannot open X file %s", msfile);
  424.       return FALSE;
  425.    } /* if */
  426.  
  427.    fprintf(stream, "# third party request, job id\n" );
  428.    fprintf(stream, "J %s\n",               job_name );
  429.    fprintf(stream, "F %s/%s/%s %s\n",      spooldir, src_syst, dest_file, src_file );
  430.    fprintf(stream, "C uucp -C %s %s!%s\n", src_file, dest_syst, dest_file );
  431.    fclose (stream);
  432.  
  433.    return TRUE;
  434. }
  435.  
  436. /*--------------------------------------------------------------------*/
  437. /*    d o _ c o p y                                                   */
  438. /*                                                                    */
  439. /*    At this point only one of the systems can be remote and only    */
  440. /*    1 hop away.  All the rest have been filtered out                */
  441. /*--------------------------------------------------------------------*/
  442.  
  443. static boolean do_copy(char *src_syst,
  444.                        char *src_file,
  445.                        char *dest_syst,
  446.                        char *dest_file)
  447. {
  448.       char    tmfile[25];               /* Unix style name for c file */
  449.       char    idfile[25];       /* Unix style name for data file copy */
  450.       char    work[66];             /* temp area for filename hacking */
  451.       char    icfilename[66];               /* our hacked c file path */
  452.       char    idfilename[66];               /* our hacked d file path */
  453.  
  454.       struct  stat    statbuf;
  455.  
  456.       long    int     sequence;
  457.       char    *remote_syst;    /* Non-local system in copy            */
  458.       char    *sequence_s;
  459.       FILE        *cfile;
  460.  
  461.       sequence = getseq();
  462.       sequence_s = JobNumber( sequence );
  463.  
  464.       remote_syst =  equal(src_syst, nodename) ? dest_syst : src_syst;
  465.  
  466.       sprintf(tmfile, spool_fmt, 'C', remote_syst, grade, sequence_s);
  467.       importpath(work, tmfile, remote_syst);
  468.       mkfilename(icfilename, spooldir, work);
  469.  
  470.       if (!equal(src_syst, nodename))  {
  471.          if (expand_path(dest_file, NULL, homedir, NULL) == NULL)
  472.             return FALSE;
  473.  
  474.          SwapSlash(src_file);
  475.  
  476.          printmsg(1, "uux - from \"%s\" - control = %s", src_syst,
  477.                   tmfile);
  478.          if ((cfile = FOPEN(icfilename, "a", TEXT)) == NULL)  {
  479.             printerr( icfilename );
  480.             printmsg(0, "uux: cannot append to %s\n", icfilename);
  481.             return FALSE;
  482.          }
  483.  
  484.          fprintf(cfile, "R %s %s %s -c D.0 0666", src_file, dest_file,
  485.                   mailbox);
  486.  
  487.          if (flags[FLG_USE_USERID])
  488.              fprintf(cfile, " %s\n", user_id);
  489.          else
  490.              fprintf(cfile, " %s\n", mailbox);
  491.  
  492.  
  493.          fclose(cfile);
  494.          return TRUE;
  495.       }
  496.       else if (!equal(dest_syst, nodename))  {
  497.  
  498.          printmsg(1,"uux - spool %s - execute %s",
  499.                   flags[FLG_COPY_SPOOL] ? "on" : "off",
  500.                   flags[FLG_QUEUE_ONLY] ? "do" : "don't");
  501.          printmsg(1,"     - dest m/c = %s  sequence = %ld  control = %s",
  502.                   dest_syst, sequence, tmfile);
  503.  
  504.          if (expand_path(src_file, NULL, homedir, NULL) == NULL)
  505.             return FALSE;
  506.  
  507.          SwapSlash(dest_file);
  508.  
  509.          if (stat(src_file, &statbuf) != 0)  {
  510.             printerr( src_file );
  511.             return FALSE;
  512.          }
  513.  
  514.          if (statbuf.st_mode & S_IFDIR)  {
  515.             printf("uux - directory name \"%s\" illegal\n",
  516.                     src_file );
  517.             return FALSE;
  518.          }
  519.  
  520.          if (flags[FLG_COPY_SPOOL]) {
  521.             sprintf(idfile , dataf_fmt, 'D', nodename, sequence_s,
  522.                               subseq());
  523.             importpath(work, idfile, remote_syst);
  524.             mkfilename(idfilename, spooldir, work);
  525.  
  526.             /* Do we need a MKDIR here for the system? */
  527.  
  528.             if (!cp(src_file, idfilename))  {
  529.                printmsg(0, "copy \"%s\" to \"%s\" failed",
  530.                   src_file, idfilename);           /* copy data */
  531.                return FALSE;
  532.             }
  533.          }
  534.          else
  535.             strcpy(idfile, "D.0");
  536.  
  537.          if ((cfile = FOPEN(icfilename, "a", TEXT)) == NULL)  {
  538.             printerr( icfilename );
  539.             printf("uux: cannot append to %s\n", icfilename);
  540.             return FALSE;
  541.          }
  542.  
  543.          fprintf(cfile, "S %s %s %s -%s %s 0666", src_file, dest_file,
  544.                   mailbox, flags[FLG_COPY_SPOOL] ? "c" : " ", idfile);
  545.  
  546.          if (flags[FLG_USE_USERID])
  547.              fprintf(cfile, " %s\n", user_id);
  548.          else
  549.              fprintf(cfile, " %s\n", mailbox);
  550.  
  551.          fclose(cfile);
  552.  
  553.          return TRUE;
  554.       }
  555.       else  {
  556.          if (expand_path(src_file, NULL, homedir, NULL) == NULL)
  557.             return FALSE;
  558.          if (expand_path(dest_file, NULL, homedir, NULL) == NULL)
  559.             return FALSE;
  560.          if (strcmp(src_file, dest_file) == 0)  {
  561.             printmsg(0, "%s %s - same file; can't copy\n",
  562.                   src_file, dest_file);
  563.             return FALSE;
  564.          }
  565.          return(cp(src_file, dest_file));
  566.       }
  567. } /* do_copy */
  568.  
  569. /*--------------------------------------------------------------------*/
  570. /*    p r e a m b l e                                                 */
  571. /*                                                                    */
  572. /*    write the execute file preamble based on the global flags       */
  573. /*--------------------------------------------------------------------*/
  574.  
  575. static void preamble(FILE* stream)
  576. {
  577.  
  578.      fprintf(stream, "U %s %s\n", mailbox, nodename);
  579.  
  580.      if (flags[FLG_RETURN_STDIN]) {
  581.          fprintf(stream, "# return input on abnormal exit\n");
  582.          fprintf(stream, "B\n");
  583.      }
  584.  
  585.      if (flags[FLG_NOTIFY_SUCCESS]) {
  586.          fprintf(stream, "# return status on success\n");
  587.          fprintf(stream, "n\n");
  588.      }
  589.  
  590.      if (flags[FLG_NONOTIFY_FAIL]) {
  591.          fprintf(stream, "# don't return status on failure\n");
  592.          fprintf(stream, "N\n");
  593.      } else {
  594.          fprintf(stream, "# return status on failure\n");
  595.          fprintf(stream, "Z\n");
  596.      }
  597.  
  598.      if (flags[FLG_USE_EXEC]) {
  599.          fprintf(stream, "# use exec to execute\n");
  600.          fprintf(stream, "E\n");
  601.      } else {
  602.          fprintf(stream, "# use sh execute\n");
  603.          fprintf(stream, "e\n");
  604.      }
  605.  
  606.      if (flags[FLG_STATUS_FILE]) {
  607.         fprintf(stream, "M %s\n", st_out );
  608.      }
  609.  
  610.      if (flags[FLG_USE_USERID]) {
  611.          fprintf(stream, "# return address for status or input return\n");
  612.          fprintf(stream, "R %s\n", user_id );
  613.      }
  614.  
  615.      fprintf(stream, "# job id for status reporting\n");
  616.      fprintf(stream, "J %s\n", job_id );
  617.      return;
  618. } /* preamble */
  619.  
  620. /*--------------------------------------------------------------------*/
  621. /*    d o _ r e m o t e                                               */
  622. /*                                                                    */
  623. /*   gather data files to ship to execution system and build X file   */
  624. /*--------------------------------------------------------------------*/
  625.  
  626. static boolean do_remote(int optind, int argc, char **argv)
  627. {
  628.       FILE    *stream;           /* For writing out data              */
  629.       char    *sequence_s;
  630.  
  631.       boolean s_remote;
  632.       boolean d_remote;
  633.       boolean i_remote = FALSE;
  634.       boolean o_remote = FALSE;
  635.  
  636.       long    sequence;
  637.  
  638.       char    src_system[100];
  639.       char    dest_system[100];
  640.       char    src_file[FILENAME_MAX];
  641.       char    dest_file[FILENAME_MAX];
  642.  
  643.       char    command[BUFSIZ];
  644.  
  645.       char    msfile[FILENAME_MAX];    /* MS-DOS format name of files */
  646.       char    msname[22];              /* MS-DOS format w/o path name */
  647.  
  648.       char    tmfile[15];        /* Call file, UNIX format name       */
  649.       char    lxfile[15];        /* eXecute file for remote system,
  650.                                     UNIX format name for local system */
  651.       char    rxfile[15];        /* Remote system UNIX name of eXecute
  652.                                     file                              */
  653.       char    lifile[15];        /* Data file, UNIX format name       */
  654.       char    rifile[15];        /* Data file name on remote system,
  655.                                     UNIX format                       */
  656.       char* jobid_fmt = &spool_fmt[3];
  657.  
  658.       if (!split_path(argv[optind++], dest_system, command, FALSE)) {
  659.          printmsg(0, "uux - illegal syntax %s", argv[optind]);
  660.          return FALSE;
  661.       }
  662.  
  663.       d_remote = equal(dest_system, nodename) ? FALSE : TRUE ;
  664.  
  665. /*--------------------------------------------------------------------*/
  666. /*        OK - we have a destination system - do we know him?         */
  667. /*--------------------------------------------------------------------*/
  668.  
  669.       if ((d_remote) && (checkreal(dest_system) == BADHOST))  {
  670.          printmsg(0, "uux - bad system: %s", dest_system);
  671.          return FALSE;
  672.       }
  673.  
  674.       printmsg(9,"xsys -> %s", dest_system);
  675.       printmsg(9, "system \"%s\", rest \"%s\"", dest_system, command);
  676.  
  677.       sequence = getseq();
  678.       sequence_s = JobNumber( sequence );
  679.  
  680.       sprintf(job_id, jobid_fmt, dest_system, grade, sequence_s);
  681.  
  682. /*--------------------------------------------------------------------*/
  683. /*                     create remote X (xqt) file                     */
  684. /*--------------------------------------------------------------------*/
  685.  
  686.       sprintf(rxfile, dataf_fmt, 'X', nodename, sequence_s, subseq());
  687.       sprintf(lxfile, dataf_fmt, d_remote ? 'D' : 'X', nodename,
  688.               sequence_s, subseq());
  689.  
  690.       importpath( msname, lxfile, dest_system);
  691.       mkfilename( msfile, spooldir, msname);
  692.  
  693.       if ( (stream = FOPEN(msfile, "w", BINARY)) == NULL ) {
  694.          printerr(msfile);
  695.          printmsg(0, "uux: cannot open X file %s", msfile);
  696.          return FALSE;
  697.       } /* if */
  698.  
  699.       preamble(stream);
  700.  
  701. /*--------------------------------------------------------------------*/
  702. /*                                                                    */
  703. /*--------------------------------------------------------------------*/
  704.  
  705.       for (; optind < argc; optind++)  {
  706.  
  707.          FileType f_remote = DATA_FILE;
  708.  
  709.          if (*argv[optind] == '-') {
  710.              strcat(command," ");
  711.              strcat(command,argv[optind]);
  712.              printmsg(9, "prm -> %s", argv[optind]);
  713.              continue;
  714.          } else if (equal(argv[optind], "<")) {
  715.              if (i_remote) {
  716.                  printmsg(0, "uux - multiple intput files specified");
  717.                  return FALSE;
  718.              } else
  719.                  i_remote = TRUE;
  720.              f_remote = INPUT_FILE;
  721.              printmsg(9, "prm -> %s", argv[optind]);
  722.              optind++;
  723.          } else if (equal(argv[optind], ">")) {
  724.              if (o_remote) {
  725.                  printmsg(0, "uux - multiple output files specified");
  726.                  return FALSE;
  727.              } else
  728.                  o_remote = TRUE;
  729.              f_remote = OUTPUT_FILE;
  730.              printmsg(9, "prm -> %s", argv[optind]);
  731.              optind++;
  732.          } else if (equal(argv[optind], "|")) {
  733.              strcat(command," ");
  734.              strcat(command,argv[optind]);
  735.              printmsg(9, "prm -> %s", argv[optind]);
  736.              continue;
  737.          } else if (remove_parens(argv[optind])) {
  738.              strcat(command," ");
  739.              strcat(command,argv[optind]);
  740.              printmsg(9, "prm -> %s", argv[optind]);
  741.              continue;
  742.          }
  743.  
  744.          printmsg(9, "prm -> %s", argv[optind]);
  745.  
  746.          if (!split_path(argv[optind], src_system, src_file, TRUE)) {
  747.             printmsg(0, "uux - illegal syntax %s", argv[optind]);
  748.             return FALSE;
  749.          }
  750.  
  751.          s_remote = equal(src_system, nodename) ? FALSE : TRUE ;
  752.  
  753. /*--------------------------------------------------------------------*/
  754. /*                   Do we know the source system?                    */
  755. /*--------------------------------------------------------------------*/
  756.  
  757.          if ((s_remote) && (checkreal(src_system) == BADHOST))  {
  758.             printmsg(0, "uux - bad system %s\n", src_system);
  759.             return FALSE;
  760.          }
  761.  
  762.         if (f_remote == DATA_FILE) {
  763.            strcat(command, " ");
  764.            strcat(command, src_file);
  765.         }
  766.  
  767.         if (f_remote == OUTPUT_FILE) {
  768.            fprintf(stream, "O %s %s\n", src_file,
  769.                    (equal(src_system, dest_system) ? " " : src_system) );
  770.            continue;
  771.         } else if (f_remote == INPUT_FILE)
  772.            fprintf(stream, "I %s\n", src_file);
  773.  
  774. /*--------------------------------------------------------------------*/
  775. /*    if both source & dest are not the same we must copy src_file    */
  776. /*--------------------------------------------------------------------*/
  777.  
  778.          if (s_remote) {
  779.  
  780.             sprintf(dest_file, dataf_fmt, 'D', src_system, sequence_s,
  781.                     subseq());
  782.  
  783.             fprintf(stream, "F %s %s\n", dest_file, src_file );
  784.  
  785. /*--------------------------------------------------------------------*/
  786. /*      if source is remote and dest is local copy source to local    */
  787. /*      if source is local and dest is remote copy source to remote   */
  788. /*--------------------------------------------------------------------*/
  789.  
  790.             if ((s_remote && !d_remote) || (!s_remote && d_remote)) {
  791.                if (!do_copy(src_system, src_file, dest_system, dest_file))
  792.                    return FALSE;
  793.  
  794. /*--------------------------------------------------------------------*/
  795. /*      if both source & dest are on remote nodes we need uuxqt       */
  796. /*--------------------------------------------------------------------*/
  797.  
  798.             } else if (s_remote && d_remote) {
  799.                if (!do_uuxqt(job_id, src_system, src_file, dest_system, dest_file))
  800.                    return FALSE;
  801.                if (!do_copy(src_system, src_file, nodename, dest_file))
  802.                    return FALSE;
  803.             }
  804.  
  805.             continue;
  806.          }
  807.          printmsg(4, "system \"%s\", rest \"%s\"", src_system, src_file);
  808.       }
  809.  
  810. /*--------------------------------------------------------------------*/
  811. /*  Create the data file if any to send to the remote system          */
  812. /*--------------------------------------------------------------------*/
  813.  
  814.       if (flags[FLG_READ_STDIN]) {
  815.           if (i_remote) {
  816.               printmsg(0, "uux - multiple input files specified");
  817.               return FALSE;
  818.           }
  819.  
  820.           sprintf(rifile, dataf_fmt, 'D', nodename, sequence_s,
  821.                   subseq());
  822.           sprintf(lifile, dataf_fmt, 'D', nodename, sequence_s,
  823.                   subseq());
  824.  
  825.           importpath(msname, lifile, dest_system);
  826.           mkfilename(msfile, spooldir, msname);
  827.  
  828.           if (!CopyData( NULL, msfile )) {
  829.               remove( msfile );
  830.               return FALSE;
  831.           }
  832.  
  833.           fprintf(stream, "F %s\n", rifile);
  834.           fprintf(stream, "I %s\n", rifile);
  835.       }
  836.  
  837. /*--------------------------------------------------------------------*/
  838. /*           here finish writing parameters to the X file             */
  839. /*--------------------------------------------------------------------*/
  840.  
  841.       printmsg(4, "command \"%s\"", command);
  842.  
  843.  
  844.       fprintf(stream, "C %s\n", command);
  845.       fclose(stream);
  846.  
  847. /*--------------------------------------------------------------------*/
  848. /*                     create local C (call) file                     */
  849. /*--------------------------------------------------------------------*/
  850.  
  851.      if (d_remote) {
  852.           sprintf(tmfile, spool_fmt, 'C', dest_system,  grade, sequence_s);
  853.           importpath( msname, tmfile, dest_system);
  854.           mkfilename( msfile, spooldir, msname);
  855.  
  856.           if ( (stream = FOPEN(msfile, "w", TEXT)) == NULL) {
  857.              printerr( msname );
  858.              printmsg(0, "uux: cannot open C file %s", msfile);
  859.              return FALSE;
  860.           }
  861.  
  862.           fprintf(stream, send_cmd, lxfile, rxfile, mailbox, lxfile);
  863.  
  864.           if (flags[FLG_READ_STDIN])
  865.               fprintf(stream, send_cmd, lifile, rifile, mailbox, lifile);
  866.  
  867.           fclose(stream);
  868.      }
  869.      return TRUE;
  870. } /* do_remote */
  871.  
  872. /*--------------------------------------------------------------------*/
  873. /*    m a i n                                                         */
  874. /*                                                                    */
  875. /*    main program                                                    */
  876. /*--------------------------------------------------------------------*/
  877.  
  878. void main(int  argc, char  **argv)
  879. {
  880.    int         c;
  881.    extern char *optarg;
  882.    extern int   optind;
  883.  
  884. /*--------------------------------------------------------------------*/
  885. /*     Report our version number and date/time compiled               */
  886. /*--------------------------------------------------------------------*/
  887.  
  888.    debuglevel = 0;
  889.    banner( argv );
  890.  
  891. #if defined(__CORE__)
  892.    copywrong = strdup(copyright);
  893.    checkref(copywrong);
  894. #endif
  895.  
  896.    if (!configure( B_UUIO ))
  897.       exit(1);   /* system configuration failed */
  898.  
  899. /*--------------------------------------------------------------------*/
  900. /*                   Switch to the spool directory                    */
  901. /*--------------------------------------------------------------------*/
  902.  
  903.    tzset();                      /* Set up time zone information  */
  904.  
  905.    PushDir( spooldir );
  906.    atexit( PopDir );
  907.  
  908.    user_id = mailbox;
  909.  
  910. /*--------------------------------------------------------------------*/
  911. /*        Process our arguments                                       */
  912. /*--------------------------------------------------------------------*/
  913.  
  914. /*--------------------------------------------------------------------*
  915.  *
  916.  *   -aname    Use name as the user identification replacing the initiator
  917.  *   -b        Return whatever standard input was provided to the uux command
  918.  *   -c        Do not copy local file to the spool directory for transfer to
  919.  *   -C        Force the copy of local files to the spool directory for
  920.  *   -E        run job using exec
  921.  *   -e        run job using sh
  922.  *   -ggrade   Grade is a single letter number; lower ASCII sequence
  923.  *   -j        Output the jobid ASCII string on the standard output which is
  924.  *   -n        Do not notify the user if the command fails.
  925.  *   -p        Same as -:  The standard input to uux is made the standard
  926.  *   -r        Do not start the file transfer, just queue the job.
  927.  *   -sfile    Report status of the transfer in file.
  928.  *   -xdebug_level
  929.  *   -z        Send success notification to the user.
  930.  *
  931. /*--------------------------------------------------------------------*/
  932.  
  933.    while ((c = getopt(argc, argv, "a:bcCEejg:nprs:x:z")) !=  EOF)
  934.       switch(c) {
  935.       case '-':
  936.          flags[FLG_READ_STDIN] = TRUE;
  937.          datain = stdin;
  938.          break;
  939.       case 'a':
  940.          flags[FLG_USE_USERID] = TRUE;
  941.          user_id = optarg;
  942.          break;
  943.       case 'b':
  944.          flags[FLG_RETURN_STDIN] = TRUE;
  945.          break;
  946.       case 'c':               /* don't spool */
  947.          flags[FLG_COPY_SPOOL] = FALSE;
  948.          break;
  949.       case 'C':               /* force spool */
  950.          flags[FLG_COPY_SPOOL] = TRUE;
  951.          break;
  952.       case 'E':               /* use exec to execute */
  953.          flags[FLG_USE_EXEC] = TRUE;
  954.          break;
  955.       case 'e':               /* use sh to execute */
  956.          flags[FLG_USE_EXEC] = FALSE;
  957.          break;
  958.       case 'j':               /* output job id to stdout */
  959.          flags[FLG_OUTPUT_JOBID] = TRUE;
  960.          break;
  961.       case 'n':               /* do not notify user if command fails */
  962.          flags[FLG_NONOTIFY_FAIL] = TRUE;
  963.          break;
  964.       case 'p':
  965.          flags[FLG_READ_STDIN] = TRUE;
  966.          datain = stdin;
  967.          break;
  968.       case 'r':               /* queue job only */
  969.          flags[FLG_QUEUE_ONLY] = TRUE;
  970.          break;
  971.       case 'z':
  972.          flags[FLG_NOTIFY_SUCCESS] = TRUE;
  973.          break;
  974.       case 'g':               /* set grade of transfer */
  975.          grade = *optarg;
  976.          break;
  977.       case 's':               /* report status of transfer to file */
  978.          flags[FLG_STATUS_FILE] = TRUE;
  979.          st_out = optarg;
  980.          break;
  981.       case 'x':
  982.          debuglevel = atoi( optarg );
  983.          break;
  984.       case '?':
  985.          usage();
  986.          exit(1);
  987.          break;
  988.       default:
  989.          printmsg(0, "uux - bad argument from getopt \"%c\"", c);
  990.          exit(1);
  991.          break;
  992.    }
  993.  
  994.    if (argc - optind < 1)  {
  995.       usage();
  996.       exit(1);
  997.    }
  998.  
  999.    if (!do_remote(optind, argc, argv)) {
  1000.       printmsg(0, "uux command failed");
  1001.       exit(1);
  1002.    };
  1003.  
  1004.    if (flags[FLG_OUTPUT_JOBID])
  1005.        printf("%s\n", job_id);
  1006.  
  1007.    exit(0);
  1008. } /* main */
  1009.  
  1010. /*--------------------------------------------------------------------*/
  1011. /*    s u b s e  q                                                    */
  1012. /*                                                                    */
  1013. /*    Generate a valid sub-sequence number                            */
  1014. /*--------------------------------------------------------------------*/
  1015.  
  1016. static char subseq( void )
  1017. {
  1018.    static char next = '0' - 1;
  1019.  
  1020.    switch( next )
  1021.    {
  1022.       case '9':
  1023.          next = 'A';
  1024.          break;
  1025.  
  1026.       case 'Z':
  1027.          next = 'a';
  1028.          break;
  1029.  
  1030.       default:
  1031.          next += 1;
  1032.    } /* switch */
  1033.  
  1034.    return next;
  1035.  
  1036. } /* subseq */
  1037.